import tkinter as tk
from tkinter import messagebox
import requests
import random
import time
from datetime import datetime
import threading

# Путь к файлам
name_file_path = r"C:\Users\1\Desktop\VS 2022\Изменить имена и фамилии ВК\Имена и Фамилии.txt"
blacklist_file_path = r"C:\Users\1\Desktop\VS 2022\Изменить имена и фамилии ВК\Blacklist for ИФ.txt"
token_file_path = r"C:\Users\1\Desktop\VS 2022\Изменить имена и фамилии ВК\Токены для изменения ИФ.txt"
token_blacklist_file_path = r"C:\Users\1\Desktop\VS 2022\Изменить имена и фамилии ВК\Blacklist for tokens.txt"
output_file_path = r"C:\Users\1\Desktop\VS 2022\Изменить имена и фамилии ВК\Сохранить Новые ИФ.txt"

# Список гласных
vowels = 'аеёиоуыэюя'

# Глобальные переменные для статистики и управления
success_count = 0
failure_count = 0
success_tokens = []
failure_tokens = []
is_running = False

# Функция для изменения имени, фамилии и даты рождения
def change_name_surname(name, surname, token):
    # Проверка на окончание фамилии
    if surname[-1].lower() in vowels:
        sex = 1  # Женский пол
    else:
        sex = 2  # Мужской пол

    # Генерация случайной даты рождения
    birth_year = random.randint(int(birth_year_from_entry.get()), int(birth_year_to_entry.get()))
    birth_month = random.randint(1, 12)
    # Определение максимального числа дней в месяце
    if birth_month in [4, 6, 9, 11]:
        max_day = 30
    elif birth_month == 2:
        max_day = 29 if (birth_year % 4 == 0 and (birth_year % 100 != 0 or birth_year % 400 == 0)) else 28
    else:
        max_day = 31
    birth_day = random.randint(1, max_day)
    birth_date = f"{birth_day:02}.{birth_month:02}.{birth_year}"

    url = f'https://api.vk.com/method/account.saveProfileInfo?v=5.131&access_token={token}'
    data = {
        'first_name': name,
        'last_name': surname,
        'sex': sex,
        'bdate': birth_date
    }
    response = requests.post(url, data=data)
    return response.json(), sex, birth_date

# Функция для чтения данных из файла
def read_file(file_path):
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            return [line.strip() for line in file.readlines()]
    except Exception as e:
        messagebox.showerror("Ошибка", f"Не удалось прочитать файл: {file_path}\nОшибка: {str(e)}")
        return []

# Функция для записи данных в файл
def write_file(file_path, data):
    try:
        with open(file_path, 'a', encoding='utf-8') as file:
            file.write(data + '\n')
    except Exception as e:
        messagebox.showerror("Ошибка", f"Не удалось записать в файл: {file_path}\nОшибка: {str(e)}")

# Функция для записи в файл с разделителем
def write_separator():
    try:
        with open(output_file_path, 'a', encoding='utf-8') as file:
            file.write("\n----\n")
    except Exception as e:
        messagebox.showerror("Ошибка", f"Не удалось записать разделитель в файл: {output_file_path}\nОшибка: {str(e)}")

# Функция для получения неиспользованного токена
def get_unused_token():
    tokens = read_file(token_file_path)
    used_tokens = read_file(token_blacklist_file_path)
    for token in tokens:
        if token not in used_tokens:
            return token
    return None

# Функция для обновления текста в реальном времени
def update_log(text):
    log_text.insert(tk.END, text + "\n")
    log_text.see(tk.END)  # Прокрутка до последней записи
    root.update_idletasks()  # Обновление интерфейса в реальном времени

# Основная функция для изменения имен и фамилий в отдельном потоке
def run_process():
    global success_count, failure_count, success_tokens, failure_tokens, is_running
    success_count = 0
    failure_count = 0
    success_tokens = []
    failure_tokens = []
    is_running = True

    # Добавление разделителя перед новым блоком
    write_separator()

    update_log("=== Процесс запущен ===")
    names_and_surnames = read_file(name_file_path)
    blacklist = read_file(blacklist_file_path)

    if not names_and_surnames:
        update_log("Список имён и фамилий пуст.")
        is_running = False
        return

    try:
        delay_min = float(delay_min_entry.get())
        delay_max = float(delay_max_entry.get())
        if delay_min < 0 or delay_max < 0 or delay_min > delay_max:
            raise ValueError("Некорректный диапазон задержки.")
    except ValueError:
        messagebox.showerror("Ошибка", "Пожалуйста, введите корректные значения для задержки.")
        is_running = False
        return

    for line in names_and_surnames:
        if not is_running:  # Проверка на флаг остановки
            update_log("Процесс остановлен пользователем.")
            break
        if line in blacklist:
            continue
        name, surname = line.split()
        token = get_unused_token()
        if not token:
            update_log("Нет доступных токенов.")
            break

        # Попытка изменить имя и фамилию (первая попытка)
        response, sex, birth_date = change_name_surname(name, surname, token)

        # Определение пола
        sex_str = "мужской" if sex == 2 else "женский"
        # Определение времени
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

        if "response" in response:
            # Успешное изменение с первой попытки
            status = "Успешно"
            update_log(f"[{status}] {name} {surname} | Пол: {sex_str} | Дата рождения: {birth_date} | Время: {current_time}")
            success_count += 1
            success_tokens.append(token)
            # Запись в файлы
            write_file(blacklist_file_path, line)
            write_file(output_file_path, f"{name} {surname}")
            write_file(token_blacklist_file_path, token)
        else:
            # Если была ошибка, повторяем запрос
            if "error" in response:
                error_code = response["error"]["error_code"]
                error_msg = response["error"]["error_msg"]

                # Повторная попытка
                update_log(f"Ошибка при первой попытке изменения для {name} {surname} | Код ошибки: {error_code}, повторная попытка...")
                response, sex, birth_date = change_name_surname(name, surname, token)

                if "response" in response:
                    # Успешное изменение со второй попытки
                    status = "Успешно (вторая попытка)"
                    update_log(f"[{status}] {name} {surname} | Пол: {sex_str} | Дата рождения: {birth_date} | Время: {current_time}")
                    success_count += 1
                    success_tokens.append(token)
                    # Запись в файлы
                    write_file(blacklist_file_path, line)
                    write_file(output_file_path, f"{name} {surname}")
                    write_file(token_blacklist_file_path, token)
                else:
                    # Если вторая попытка не удалась, записываем ошибку и пропускаем аккаунт
                    if "error" in response:
                        error_code = response["error"]["error_code"]
                        error_msg = response["error"]["error_msg"]
                        update_log(f"Ошибка при второй попытке изменения для {name} {surname} | Код ошибки: {error_code}, аккаунт пропущен.")
                        failure_count += 1
                        failure_tokens.append(token)
                        # Запись с кодом ошибки в файл
                        write_file(output_file_path, f"{name} {surname} | Код ошибки: {error_code}")
                        write_file(token_blacklist_file_path, token)

        # Обновление меток статистики
        success_label.config(text=f"Успешно: {success_count}")
        failure_label.config(text=f"Неуспешно: {failure_count}")

        # Случайная задержка
        delay = random.uniform(delay_min, delay_max)
        update_log(f"Задержка: {delay:.1f} сек")
        time.sleep(delay)  # Задержка перед использованием следующего токена

    update_log("=== Процесс завершён ===")
    is_running = False

# Функция для запуска процесса в отдельном потоке
def start_process():
    if not is_running:  # Проверка, чтобы не запускать новый процесс, если текущий еще выполняется
        threading.Thread(target=run_process).start()
    else:
        messagebox.showwarning("Внимание", "Процесс уже выполняется.")

# Функция для остановки процесса
def stop_process():
    global is_running
    is_running = False

# Функция для отображения успешных токенов
def show_success_tokens():
    if success_tokens:
        tokens_text = "\n".join(success_tokens)
        messagebox.showinfo("Успешные токены", tokens_text)
    else:
        messagebox.showinfo("Успешные токены", "Нет успешных токенов")

# Функция для отображения неуспешных токенов
def show_failure_tokens():
    if failure_tokens:
        tokens_text = "\n".join(failure_tokens)
        messagebox.showinfo("Неуспешные токены", tokens_text)
    else:
        messagebox.showinfo("Неуспешные токены", "Нет неуспешных токенов")

# Создание контекстного меню для копирования
def create_context_menu(event):
    context_menu = tk.Menu(root, tearoff=0)
    context_menu.add_command(label="Копировать", command=lambda: root.focus_get().event_generate("<<Copy>>"))
    context_menu.tk_popup(event.x_root, event.y_root)

# Создание графического интерфейса
root = tk.Tk()
root.title("Изменить имена и фамилии ВК")
root.geometry("800x600")  # Увеличение размеров окна

start_button = tk.Button(root, text="Запустить", command=start_process)
start_button.pack(pady=10)

stop_button = tk.Button(root, text="Остановить", command=stop_process)
stop_button.pack(pady=10)

delay_min_label = tk.Label(root, text="Задержка от (сек):")
delay_min_label.pack()
delay_min_entry = tk.Entry(root)
delay_min_entry.insert(0, "2")  # Задержка "от" по умолчанию 2 секунды
delay_min_entry.pack(pady=5)

delay_max_label = tk.Label(root, text="Задержка до (сек):")
delay_max_label.pack()
delay_max_entry = tk.Entry(root)
delay_max_entry.insert(0, "3")  # Задержка "до" по умолчанию 3 секунды
delay_max_entry.pack(pady=5)

birth_year_from_label = tk.Label(root, text="Год рождения от:")
birth_year_from_label.pack()
birth_year_from_entry = tk.Entry(root)
birth_year_from_entry.insert(0, "1970")  # Год рождения от по умолчанию
birth_year_from_entry.pack(pady=5)

birth_year_to_label = tk.Label(root, text="Год рождения до:")
birth_year_to_label.pack()
birth_year_to_entry = tk.Entry(root)
birth_year_to_entry.insert(0, "1990")  # Год рождения до по умолчанию
birth_year_to_entry.pack(pady=5)

# Метки для отображения статистики
success_label = tk.Label(root, text="Успешно: 0", font=("Helvetica", 12, "bold"), fg="green")
success_label.pack(pady=5)

failure_label = tk.Label(root, text="Неуспешно: 0", font=("Helvetica", 12, "bold"), fg="red")
failure_label.pack(pady=5)

# Кнопки для отображения токенов
show_success_button = tk.Button(root, text="Показать успешные токены", command=show_success_tokens)
show_success_button.pack(pady=5)

show_failure_button = tk.Button(root, text="Показать неуспешные токены", command=show_failure_tokens)
show_failure_button.pack(pady=5)

# Текстовое поле для лога с поддержкой контекстного меню
log_text = tk.Text(root, height=20, width=100, wrap=tk.WORD)
log_text.pack(pady=10)
log_text.bind("<Button-3>", create_context_menu)  # Привязка правой кнопки мыши к контекстному меню

root.mainloop()
